package yxy.game.pm2.module.kow;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.joda.time.DateTime;

import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.txdijfwinreward;
import yxy.cherry.data.bean.txdyjingcai;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format.FormatType;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.ServerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.RedisLock;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.module.rank.RankWorship;
import yxy.game.pm2.bean.module.rank.RankWorshipPlayer;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.KowMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.BattleHandle;
import yxy.game.pm2.module.battle.BattleModule;
import yxy.game.pm2.module.battle.BattleType;
import yxy.game.pm2.module.battle.TeamModule;
import yxy.game.pm2.module.player.PlayerHandle;
import yxy.game.pm2.module.stat.StatHandle;

public class KowHandle {

	/** 活动状态 */
	static public enum KowState {
		PREPARE(0), // 新赛季未开始
		GROUP(1), // 小组赛准备中
		GROUPSET(2), // 小组赛进行中
		QUARTER(3), // 8强赛竞猜
		SEMI(4), // 4强赛竞猜
		FINAL(5), // 决赛竞猜
		OFFSEASON(6), // 赛后展示
		;

		private int number;

		private KowState(int number) {
			this.number = number;
		}

		public int getNumber() {
			return number;
		}
	}

	/** 决赛Code */
	static public enum KowFinalCode {
		F12(1), //
		F34(2), //
		F56(3), //
		F78(4), //
		F1256(5), //
		F3478(6), //
		FINAL(7), //
		;

		private int number;

		private KowFinalCode(int number) {
			this.number = number;
		}

		public int getNumber() {
			return number;
		}

		static public KowFinalCode forNumber(int value) {
			switch (value) {
			case 1:
				return F12;
			case 2:
				return F34;
			case 3:
				return F56;
			case 4:
				return F78;
			case 5:
				return F1256;
			case 6:
				return F3478;
			case 7:
				return FINAL;
			}
			return null;
		}
	}

	/** 参赛等级 */
	static public enum KowRankLevel {
		None(0), // 未参赛
		Winner(1), // 冠军
		RunnerUp(2), // 亚军
		Four(3), // 四强
		Eight(4), // 八强
		Group(5), // 小组未出线
		GroupFirst(6), // 小组第一
		GroupSecond(7), // 小组第二
		GroupThird(8), // 小组第三
		GroupFourthToTenth(9), // 小组四到十

		;

		private int number;

		private KowRankLevel(int number) {
			this.number = number;
		}

		public int getNumber() {
			return number;
		}
	}

	public Result mainInfo(String playerCode, KowMessage.KowUIResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule kowModule = KowModule.get(areaBean.getGroupId());
		KowPlayerModule kowPlayerModule = KowPlayerModule.get(playerCode);
		try {
			if (kowPlayerModule.tryLock()) {
				if (!kowPlayerModule.getCode().equals(kowModule.getCode())) {
					kowPlayerModule.setNowLevel(KowRankLevel.None);
					kowPlayerModule.set();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			kowPlayerModule.unlock();
		}
		RankKowGroup rankKowGroup = new RankKowGroup(areaBean.getGroupId(), kowPlayerModule.getGroup());
		RankKowKing rankKowKing = new RankKowKing(areaBean.getGroupId());
		RankWorship worship = rankKowKing.getWorship();
		RankWorshipPlayer worshipPlayer = RankWorshipPlayer.get(playerCode, worship);

		response.setState(KowMessage.KowState.forNumber(kowModule.getState().getState().getNumber()));
		response.setNextTime(kowModule.stateTime().getMillis());
		response.setNowLevel(KowMessage.KowRankLevel.forNumber(kowPlayerModule.getNowLevel().getNumber()));
		response.setBestLevel(KowMessage.KowRankLevel.forNumber(kowPlayerModule.getBestLevel().getNumber()));
		response.setFans(rankKowKing.getWorship().getScore(playerCode));
		response.setGroupRank(rankKowGroup.rank(playerCode));
		response.setGroup(kowPlayerModule.getGroup());

		Collection<RankEntry> kingEntries = rankKowKing.range(1, 4);

		for (RankEntry entry : kingEntries) {
			String kingCode = entry.getKey();
			int value = entry.getValue().intValue();

			KowMessage.KowKing.Builder builder = KowMessage.KowKing.newBuilder();
			builder.setLevel(KowMessage.KowRankLevel.forNumber(value));
			builder.setFans(worship.getScore(kingCode));
			builder.setLiked(worshipPlayer.getWorshiped().contains(kingCode));
			builder.setPlayerInfo(new PlayerHandle().playerSimpleInfo(kingCode));
			response.addKing(builder);
		}

		return Result.Success;
	}

	public Result mainGroupInfo(String playerCode, KowMessage.KowGroupUIResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule kowModule = KowModule.get(areaBean.getGroupId());
		KowPlayerModule kowPlayerModule = KowPlayerModule.get(playerCode);
		if (!kowPlayerModule.getCode().equals(kowModule.getCode())) {
			return Result.KowNoIn;// 未参赛
		}
		RankKowGroup rankKowGroup = new RankKowGroup(areaBean.getGroupId(), kowPlayerModule.getGroup());

		{
			int rank = rankKowGroup.rank(playerCode);
			long score = rankKowGroup.get(playerCode).getValue();

			response.setEndTime(kowModule.stateTime().getMillis());
			response.setGroupRank(rank);
			response.setGroupScore(score);
			response.setTimes(kowPlayerModule.remainTimes());
			response.setRefresh(kowPlayerModule.getRefreshtimes());
			response.setGroup(kowPlayerModule.getGroup());
		}
		response.addAllOppos(oppos(kowPlayerModule, rankKowGroup));

		return Result.Success;
	}

	public Result finalInfo(String playerCode, KowMessage.KowFinalUIResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule kowModule = KowModule.get(areaBean.getGroupId());
		if (kowModule.getFinals().size() <= 0) {
			return Result.KowFinalNotStart;// 决赛阶段尚未开始
		}
		HashSet<String> playerCodes = new HashSet<>();
		for (KowFinal kowFinal : kowModule.getFinals().values()) {
			playerCodes.add(kowFinal.getPlayer1().getPlayerCode());
			playerCodes.add(kowFinal.getPlayer2().getPlayerCode());
		}
		for (String code : playerCodes) {
			KowPlayerModule kowPlayerModule = KowPlayerModule.get(code);

			KowMessage.KowKing.Builder builder = KowMessage.KowKing.newBuilder();
			builder.setGroup(kowPlayerModule.getGroup());
			builder.setLevel(KowMessage.KowRankLevel.forNumber(kowPlayerModule.getNowLevel().getNumber()));
			builder.setPlayerInfo(new PlayerHandle().playerSimpleInfo(code));
			response.addPlayers(builder);
		}

		response.setState(KowMessage.KowState.forNumber(kowModule.getState().getState().getNumber()));
		response.setNextTime(kowModule.stateTime().getMillis());

		return Result.Success;
	}

	public Result finalFanInfo(String playerCode, KowMessage.KowFinalInfoResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule kowModule = KowModule.get(areaBean.getGroupId());
		if (kowModule.getFinals().size() <= 0) {
			return Result.KowFinalNotStart;// 决赛阶段尚未开始
		}

		KowFinalCode[] finalCodes = new KowFinalCode[] { KowFinalCode.FINAL, KowFinalCode.F1256, KowFinalCode.F3478, KowFinalCode.F12, KowFinalCode.F34,
				KowFinalCode.F56, KowFinalCode.F78 };
		for (KowFinalCode finalCode : finalCodes) {
			KowFinal kowFinal = kowModule.getFinals().get(finalCode);
			if (kowFinal == null) {
				continue;
			}
			response.addFinalInfo(packFinalInfo(playerCode, kowFinal));
		}

		return Result.Success;
	}

	public Result fan(String playerCode, String fanCode, KowFinalCode finalCode, KowMessage.KowFinalFanResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		RedisLock lock = KowModule.lock(areaBean.getGroupId());
		try {
			if (lock.tryLock()) {
				KowModule kowModule = KowModule.get(areaBean.getGroupId());

				if (kowModule.getFinals().size() <= 0) {
					return Result.KowFinalNotStart;// 决赛阶段尚未开始
				}
				KowFinal kowFinal = kowModule.getFinals().get(finalCode);
				if (kowFinal == null) {
					return Result.ParamError;
				}
				if (kowFinal.getWinner() != null) {
					return Result.KowFansFinalOver;// 这场比赛已经结束
				}
				KowFinalPlayer fanPlayer = kowFinal.player(fanCode);
				KowFinalPlayer oppoPlayer = kowFinal.oppo(fanCode);
				if (fanPlayer == null || oppoPlayer == null) {
					return Result.ParamError;
				}
				if (fanPlayer.getFans().contains(playerCode) || oppoPlayer.getFans().contains(playerCode)) {
					return Result.KowFansHasVoted;// 你已经投过票了
				}
				txdyjingcai data = kowFinal.data();
				Currency cost = Currency.create(CurrencyType.CT_钱币, 0, data.getCostnum());
				try {
					new CurrencyHandle().cost(playerCode, CCReason.天下第一, cost);
				} catch (CurrencyNotEnoughException e) {
					return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());
				}
				fanPlayer.getFans().add(playerCode);
				kowModule.set();

				response.setFinalInfo(packFinalInfo(playerCode, kowFinal));
			}
		} catch (Exception e) {
			return Result.DataError;
		} finally {
			lock.unlock();
		}
		return Result.Success;
	}

	private KowMessage.KowFinalInfo packFinalInfo(String playerCode, KowFinal kowFinal) {
		KowMessage.KowFinalInfo.Builder infobuilder = KowMessage.KowFinalInfo.newBuilder();
		infobuilder.setFinalCode(KowMessage.KowFinalCode.forNumber(kowFinal.getFinalCode().getNumber()));
		{
			KowFinalPlayer finalPlayer = kowFinal.getPlayer1();
			KowMessage.KowKing.Builder builder = KowMessage.KowKing.newBuilder();
			builder.setFans(finalPlayer.getFans().size());
			builder.setLiked(finalPlayer.getFans().contains(playerCode));
			builder.setPlayerInfo(new PlayerHandle().playerSimpleInfo(finalPlayer.getPlayerCode()));
			infobuilder.addPlayers(builder);
		}
		{
			KowFinalPlayer finalPlayer = kowFinal.getPlayer2();
			KowMessage.KowKing.Builder builder = KowMessage.KowKing.newBuilder();
			builder.setFans(finalPlayer.getFans().size());
			builder.setLiked(finalPlayer.getFans().contains(playerCode));
			builder.setPlayerInfo(new PlayerHandle().playerSimpleInfo(finalPlayer.getPlayerCode()));
			infobuilder.addPlayers(builder);
		}
		if (kowFinal.getWinner() != null) {
			int battleResult = kowFinal.getWinner().getPlayerCode().equals(kowFinal.getPlayer1().getPlayerCode()) ? 1 : 2;
			infobuilder.setRecord(kowFinal.getRecord());
			infobuilder.setBattleResult(battleResult);
		}

		return infobuilder.build();
	}

	public Collection<KowMessage.KowPlayer> oppos(KowPlayerModule kowPlayerModule, RankKowGroup rankKowGroup) {
		ArrayList<KowMessage.KowPlayer> oppos = new ArrayList<>();
		for (String oppoCode : kowPlayerModule.getOppo()) {
			int rank = rankKowGroup.rank(oppoCode);
			long score = rankKowGroup.get(oppoCode).getValue();

			KowMessage.KowPlayer.Builder builder = KowMessage.KowPlayer.newBuilder();
			builder.setGroupRank(rank);
			builder.setGroupScore(score);
			builder.setPlayerInfo(new PlayerHandle().playerSimpleInfo(oppoCode));
			oppos.add(builder.build());
		}
		return oppos;
	}

	public void refreshOppo(KowPlayerModule playerModule, RankKowGroup rankKowGroup) {
		String playerCode = playerModule.getPlayerCode();
		int size = 3;// 对手数量
		ArrayList<String> oppoList = new ArrayList<>();
		Collection<RankEntry> randomOppo = rankKowGroup.randomEntry(playerCode, 100, 100, size);
		for (RankEntry entry : randomOppo) {
			oppoList.add(entry.getKey());
		}
		playerModule.setOppo(oppoList);
		playerModule.set();
	}

	/** 小组赛战斗 */
	public Result battleResponseExecute(String playerCode, String oppoCode, KowMessage.KowGroupChanllengeResponse.Builder response) throws Exception {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule module = KowModule.get(areaBean.getGroupId());
		if (!module.getState().getState().equals(KowState.GROUPSET)) {
			return Result.KowGroupNotStart;// 小组赛未到战斗时间
		}
		if (playerCode.equals(oppoCode)) {
			return Result.ParamError;// 不能挑战自己
		}
		KowPlayerModule playerModule = KowPlayerModule.get(playerCode);
		if (!playerModule.getCode().equals(module.getCode())) {
			return Result.KowNoIn;// 你未参赛
		}
		if (!playerModule.getOppo().contains(oppoCode)) {
			return Result.ParamError;// 需要刷新对手
		}
		if (playerModule.remainTimes() <= 0) {
			return Result.WorldBossTimesLack;// TODO 挑战次数已经用完
		}

		RankKowGroup rankKowGroup = new RankKowGroup(areaBean.getGroupId(), playerModule.getGroup());
		RankEntry playerEntry = rankKowGroup.get(playerCode);
		RankEntry oppoEntry = rankKowGroup.get(oppoCode);
		if (playerEntry == null || oppoEntry == null) {
			return Result.DataError;
		}

		playerModule.setTimes(playerModule.getTimes() + 1);
		playerModule.set();

		BattleHandle battleHandle = new BattleHandle();

		BattleModule battleModule = handleBattle(playerCode, oppoCode);

		boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

		// 处理分数
//		int score = fomula.天下第一积分获得积分规则.doubleValue(100, 20).intValue();
		int score = score(playerEntry.getValue(), oppoEntry.getValue()).intValue();
		int scoreChangeA = 0;
		int scoreChangeB = 0;
		Currencies rewards = new Currencies();
		txdijfwinreward data = DataCenter.getData(101, txdijfwinreward.class);
		if (isWin) {
			scoreChangeA = score * data.getActivewinscore() / 10000;
			scoreChangeB = score * data.getPassivesurrenderscore() / 10000;

			rewards.add(Currency.create(data.getWinrewardtype(), data.getWinrewardid(), data.getWinrewardnum()));

			// 刷新对手
			refreshOppo(playerModule, rankKowGroup);
		} else {
			scoreChangeA = score * data.getActivesurrenderscore() / 10000;
			scoreChangeB = score * data.getPassivewinscore() / 10000;

			rewards.add(Currency.create(data.getSurrenderrewardtype(), data.getSurrenderrewardid(), data.getSurrenderrewardnum()));
		}
		long playerScore = playerEntry.getValue() + scoreChangeA;
		long oppoScore = oppoEntry.getValue() - scoreChangeB;
		rankKowGroup.put(playerCode, playerScore);
		rankKowGroup.put(oppoCode, oppoScore);

		new CurrencyHandle().addCurrency(playerCode, CCReason.天下第一, rewards);

		// 记录
		{
			KowRecord record = new KowRecord();
			record.setAttackerCode(playerCode);
			record.setDefenderCode(oppoCode);
			record.setDate(DateTime.now());
			record.setBattleResult(battleModule.getBattleResult());
//			arenaRecord.setRecordCode(battleRecord.getCode());
			record.setScoreChangeAttacker(scoreChangeA);
			record.setScoreChangeDefender(scoreChangeB);
			KowRecord.add(playerCode, record);
			KowRecord.add(oppoCode, record);
		}

		// 封装消息
		{
			KowMessage.KowFighter.Builder fighterA = packFighter(playerCode);
			fighterA.setScore(playerScore);
			fighterA.setChange(scoreChangeA);
			KowMessage.KowFighter.Builder fighterB = packFighter(oppoCode);
			fighterB.setScore(oppoScore);
			fighterB.setChange(scoreChangeB);

			BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
			builder.setPlayback(battleHandle.playback(battleModule));// , team_a, team_b));

			response.setBattleResp(builder);// 录像
			response.setBattleResult(battleModule.getBattleResult().getNumber());// 战果

			response.setFighterA(fighterA);// 进攻方
			response.setFighterB(fighterB);// 防守方

			response.addAllRewards(new CurrencyHandle().packItems(rewards));
		}

		return Result.Success;
	}

	private Double score(double active, double passive) {
		if (active >= passive) {
			return 10d;
		}
		return Math.ceil(10 + Math.min((passive * 0.01), 50));
	}

	public BattleModule handleBattle(String playerCode1, String playerCode2) {
		BattleHandle battleHandle = new BattleHandle();

		BattleModule battleModule = BattleModule.create(playerCode1);
		battleModule.setType(BattleType.KOW);
		battleModule.setCode(BattleType.KOW.name());

		// 玩家的team
		TeamModule teamA = battleHandle.teamPlayer(playerCode1, FormatType.普通);
		battleModule.setTeamA(teamA);

		// 玩家的team
		TeamModule teamB = battleHandle.teamPlayer(playerCode2, FormatType.普通);
		battleModule.setTeamB(teamB);

		//todo 修改登录时间，3天后自动清除缓存
		StatHandle.stat_用户登录状态更新(playerCode1);
		StatHandle.stat_用户登录状态更新(playerCode2);

		Team team_a = teamA.team(true);
		Team team_b = teamB.team(false);
		team_a.setTeam对手(team_b);
		team_b.setTeam对手(team_a);

		// 处理战斗
		battleHandle.battleExecute(battleModule, team_a, team_b, 20);
		return battleModule;
	}

	public KowMessage.KowFighter.Builder packFighter(String playerCode) {
		KowMessage.KowFighter.Builder builder = KowMessage.KowFighter.newBuilder();
		PlayerBean player = PlayerBean.get(playerCode);
		builder.setPlayerCode(player.getCode());
		builder.setNickname(player.getName());
		builder.setHead(player.getHead());
		builder.setHeadFrame(player.getHeadframe());
		builder.setLevel(player.getLevel());
		return builder;
	}

	public Result record(String playerCode, KowMessage.KowRecordResponse.Builder response) {
		PlayerBean playerBean = PlayerBean.get(playerCode);
		ServerBean serverBean = ServerBean.get(playerBean.getServerId());
		AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		KowModule kowModule = KowModule.get(areaBean.getGroupId());
		KowPlayerModule kowPlayerModule = KowPlayerModule.get(playerCode);
		if (!kowPlayerModule.getCode().equals(kowModule.getCode())) {
			return Result.KowNoIn;// 未参赛
		}

		List<KowRecord> list = KowRecord.get(playerCode);
		for (KowRecord record : list) {
			boolean isAttacker = record.getAttackerCode().equals(playerCode);

			KowMessage.KowRecord.Builder builder = KowMessage.KowRecord.newBuilder();
			builder.setAttack(isAttacker);
//			builder.setRecord(record.getRecordCode());
			builder.setDate(record.getDate().getMillis());
			builder.setOppoInfo(new PlayerHandle().playerSimpleInfo(isAttacker ? record.getDefenderCode() : record.getAttackerCode()));
			builder.setResult(record.getBattleResult().getNumber());
			builder.setScore(isAttacker ? record.getScoreChangeAttacker() : record.getScoreChangeDefender());

			response.addRecords(builder);
		}

		return Result.Success;
	}

	static public enum KowStepEnum {
		// mon
		STEP_PRE(KowState.PREPARE), // 新赛季未开始
		STEP_GROUP_1(KowState.GROUP), // 小组赛第1轮准备中
		STEP_GROUP_1_SET(KowState.GROUPSET), // 小组赛第1轮进行中
		// tue
		STEP_GROUP_2(KowState.GROUP), // 小组赛第2轮准备中
		STEP_GROUP_2_SET(KowState.GROUPSET), // 小组赛第2轮进行中
		// wed
		STEP_GROUP_3(KowState.GROUP), // 小组赛第3轮准备中
		STEP_GROUP_3_SET(KowState.GROUPSET), // 小组赛第3轮进行中
		// thr
		STEP_GROUP_4(KowState.GROUP), // 小组赛第4轮准备中
		STEP_GROUP_4_SET(KowState.GROUPSET), // 小组赛第4轮进行中
		// fri
		STEP_QUARTER(KowState.QUARTER), // 8强赛竞猜
		// sat
		STEP_SEMI(KowState.SEMI), // 4强赛竞猜
		// sun
		STEP_FINAL(KowState.FINAL), // 决赛竞猜
		STEP_OFFSEASON(KowState.OFFSEASON),// 赛后展示
		;

		private KowState state;

		private KowStepEnum(KowState state) {
			this.state = state;
		}

		public KowState getState() {
			return state;
		}

		public KowStepEnum getNext() {
			switch (this) {
			case STEP_PRE:
				return STEP_GROUP_1;
			case STEP_GROUP_1:
				return STEP_GROUP_1_SET;
			case STEP_GROUP_1_SET:
				return STEP_GROUP_2;
			case STEP_GROUP_2:
				return STEP_GROUP_2_SET;
			case STEP_GROUP_2_SET:
				return STEP_GROUP_3;
			case STEP_GROUP_3:
				return STEP_GROUP_3_SET;
			case STEP_GROUP_3_SET:
				return STEP_GROUP_4;
			case STEP_GROUP_4:
				return STEP_GROUP_4_SET;
			case STEP_GROUP_4_SET:
				return STEP_QUARTER;
			case STEP_QUARTER:
				return STEP_SEMI;
			case STEP_SEMI:
				return STEP_FINAL;
			case STEP_FINAL:
				return STEP_OFFSEASON;
			default:
				return STEP_PRE;
			}
		}
	}
}
